﻿//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//    Crolengi, this program (a part of program) is gameengine based on C++\Directx
//    Copyright (C) 2008 Pashinin Anton Alekseevich (Crol)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//    (INCLUDING NEGLIGENCE OR OTHERWISE) 
//    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
//    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//    Contacts: 
//    Mail: crolengi@gmail.com
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef  CObject_PhysX_VSM_h
#define  CObject_PhysX_VSM_h

#include <d3d9.h>
#include <d3dx9.h>

#include "..\\import\\CRLEngi_strings_lib\\CRLEngi_strings.h"
#include "..\\import\\param_trees_lib\\param_trees.h"
#include "object_super_class.h"

#include "include\\Managers\\Effect_Manager.h"
#include "include\\Managers\\Light_Manager.h"

#include "include\\Utils\\defines01.h"  

#include "include\\Managers\\PhysX_Main.h"
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
/////   :: КЛАСС ФИЗИЧЕСКОГО, СКРИПТОВОГО ОБЪЕКТА ::
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CObject_PhysX_VSM:public CObject_PhysX{
public:
// структура скриптовой команды
struct Command_struct{
	   //имя
	   CRLEngi_string  name;
	   //переданные параметры
	   CRLEngi_string  params;
	   float           x;
	   float           y;
	   float           z;
	   //время рождения
	   long            time_start;
	   //время выполнения
	   long            time_to_end;
	   // дополнительные параметры
	   float           mem1;
	   float           mem2;
	   float           mem3;
	   //началось ли уже выполнение?
	   bool            FirstRun;
       // ??
	   bool            RaiseEvent;
	   CRLEngi_string  EndEvent;
};

list       CommandStack;
CRLEngi_string  S1,S2;
char  c[512],EndEvent[512];
float x,y,z; int rez,time;
int time_until_end,time_passed;
CRLEngi_string EEvent;
CRLEngi_string params;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////   Анализ команд
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool    AnalyzeCommand(CRLEngi_string  Command){

	 S1.clear();S2.clear();
	 //Command.DivideTwoParameters(&S1,&S2);	
	sscanf(Command.getChars(),"%s %64[^'@']",c,EndEvent);
	 S1=c; S2=EndEvent;

	 S1.HideHoles();

	 if (S1 == "setLinearVelocity"){ //"object setForce x,y,z str_type bool_wakeup"
		   
		   x=y=z=rez=0;
	       rez = sscanf(Command.getChars(),"%s %f,%f,%f %s",c,&x,&y,&z,EndEvent);
		   //switch (type){
			 phys_object->setLinearVelocity(NxVec3(x,y,z)); //break;
			 //case 2:phys_object->addForce(NxVec3(x,y,z),NX_IMPULSE  ,true);break;
			 //case 3:phys_object->addForce(NxVec3(x,y,z),NX_VELOCITY_CHANGE ,(bool)wakeup);break;
			 ///case 4:phys_object->addForce(NxVec3(x,y,z),NX_SMOOTH_IMPULSE ,false);break;
			 //case 5:phys_object->addForce(NxVec3(x,y,z),NX_SMOOTH_VELOCITY_CHANGE  ,(bool)wakeup);break;
			 //case 6:phys_object->addForce(NxVec3(x,y,z),NX_ACCELERATION   ,(bool)wakeup);break;
			 //case 0:return false;
		   //}		   
		   S1 = EndEvent;
		    Console->Lua_SendCommand(&Name,&S1);
		   //Console->AddText(Command,3);
	 }else 
		 if (S1 == "wait"){

			Command_struct *a;
			 a = new Command_struct();
			 //char  c[512];
			 //int time,rez;
			 //char  EndEvent[512];
			 rez = sscanf(Command.getChars(),"%s %d %s",c,&time,EndEvent);

			 if (rez!=3){
				 rez = sscanf(Command.getChars(),"%s %d",c,&time);
				 a->RaiseEvent = false;
			 }
			 else
				 a->RaiseEvent = true;

			 
			 EEvent = EndEvent;

			 a->name = c;
			 a->time_start = Console->GetCurrientTime_mseconds();
			 a->time_to_end = time;
			 a->EndEvent = EEvent;
             CommandStack.Add(a);

			 
			 //params = "Объекту: "; params += Name; params += " Добавлена команда:";  params += Command;

			 //Console->AddText(params,3);
		 }            
		 return true;
}



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////   запускает команды из стека
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void run_commands(){
  // прогуляемся по стеку команд
  for(list::Item* I=CommandStack.GetItems(); I!=NULL; I=I->next)
  {
    //надоже, что то нашли, но что?
    Command_struct *obj =(Command_struct*)I->ptr;

	if(obj->name=="wait"){

			 //консоль то поди не видна?
			 if(!Console->visible){
			   
			   //и сколь времени прошло уже?
			   time_passed    = Console->GetCurrientTime_mseconds() - obj->time_start;
			   // а осталось?
			   time_until_end = obj->time_to_end - (Console->GetCurrientTime_mseconds() - obj->time_start);

			   if (time_until_end<1){
				   //ну удаляем его нафиг
				   CommandStack.RemoveItem(I);
				   
				   if (obj->RaiseEvent)
					   Console->Lua_SendCommand(&Name,&obj->EndEvent);

				   delete(&obj->EndEvent);
				   //if (obj->params!=NULL)
				   //delete(&obj->params);
				   
				   delete(obj);
				   
				   obj = NULL;
				   

				   break;
			   }
			 
			 }
	}
    
		 
  }//--for
}



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////   инициализация дополнительных параметров
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void MousePick(D3DXVECTOR3 *vRayDir,D3DXVECTOR3 *vayOrig){
if (pMesh!=NULL){   
	D3DXVECTOR3 vPickRayDir = *vRayDir;
	D3DXVECTOR3 vPickRayOrig = *vayOrig;

	BOOL cool = false;
	float distance = 0;
	float d3dMat[16];

    D3DXMATRIX matWorld;

   phys_object->getGlobalPose().getColumnMajor44( d3dMat );
   matWorld = d3dMat;
   //(*vPickRayOrig) *=matWorld;
   D3DXMatrixInverse(&matWorld,NULL,&matWorld);
   D3DXVec3TransformCoord(&vPickRayOrig,&vPickRayOrig,&matWorld);
   D3DXVec3TransformNormal(&vPickRayDir, &vPickRayDir, &matWorld);
   
   D3DXIntersect(pMesh,&vPickRayOrig,&vPickRayDir,&cool,NULL,NULL,NULL,&distance,NULL,NULL);

   if ((cool)&&(distance>0)&&(distance<40000)){
	   CRLEngi_string command;//, N;// N =Name;
	   command = "mouse_pick";
	   Console->Lua_SendCommand(&Name,&command);   
   }
}
}
bool InitParameters3(){
   //	ScriptLine1.fresh();
		//int a;
		//a = ScriptLine1.AddToId(0,true,"_ROOT_");
		//ScriptLine1.fresh();
		//ScriptLine1.AddToId(0,true,"_ROOT_");


	            int id    = ObjProperties.iLookId("_LUA_SCRIPT_FILE_");
			    int count = ObjProperties.iCountParams(id) + ObjProperties.iCountKnots(id);
			    if ((id>0)&&(count>0)){
			    
				int id2 = ObjProperties.TopId(id);
				//LPCSTR Lfilename;
				CRLEngi_string  filename;
				filename = (ObjProperties.iLookName(id2));

				Console->Lua_Open_Script(&filename);
				//Lfilename = filename.getChars();


				}

		return true;
}


CObject_PhysX_VSM(D3DXMATRIXA16*            GMatrix,
		       char*                     FProperties,
			   LPDIRECT3DDEVICE9        *Device,
			   CLREngi_Effect_Manager   *Eff_Manager,
			   CLREngi_Light_Manager    *L_Manager,
		       CLREngi_Console           *Cnsl){ 

		Console=Cnsl;

		GOMatrixDef = *GMatrix;             // получаем мировую матрицу проекции
	    D3DXMatrixIdentity(&GOMatrix);     // обрабатываем созданную матрицу

		CRLEngi_string file;
		file = FProperties;
		ObjProperties.iLoadFromFile(file); //загрузка параметров

		dwNumMaterials= 0 ;
		Position = D3DXVECTOR3(0.0f,0.0f,0.0f);		

		Effect_Manager = Eff_Manager;

		Light_Manager = L_Manager;

		pd3dDevice = Device;

		aEff=NULL;

		g_pTexture_Light_Map = NULL;

		Name = "ABC";

	};
CObject_PhysX_VSM(){};
};

#endif 